﻿using CacheManager.Core;
using System;
using System.Linq;
using System.Threading.Tasks;
using Yz.Base;

namespace Yz.Cache
{
    public class CacheManagerUitility : BaseCacheUitility, ICacheUitility
    {
        #region 从缓存中获得数据（有委托）
        /// <summary>
        /// 具体执行缓存委托或更新缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="Func">委托方法</param>
        /// <param name="args">至少有2个参数（从右往左（从后往前），1：是否去更新缓存，2：CacheDbTime 对象（包含时间和数据库索引）</param>
        /// <returns>List<T></returns>
        protected override ReturnList<T> GetDataListFromCache<T>(Delegate func, object[] args)
        {
            ReturnList<T> itemList = new ReturnList<T>();
            if (args.Length < 2)
            {
                return itemList;
            }
            var cachePara = base.GetCachePara(func, args);
            string cacheKey = GetCacheKey(cachePara.Key);
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, cachePara.Expiry);
            ICacheManager<ReturnList<T>> cacheManager = cmHelper.GetReturnCacheManager<T>();
            string cacheRegion = cachePara.DbNum.ToString();
            if (cachePara.Update || !cacheManager.Exists(cacheKey, cacheRegion))//存在
            {
                itemList = (ReturnList<T>)func.DynamicInvoke(args.Take(args.Length - 2).ToArray());
                cacheManager.Add(cacheKey, itemList, cacheRegion);
            }
            else
            {
                itemList = cacheManager.Get(cacheKey, cacheRegion);
            }
            return itemList;
        }
        /// <summary>
        /// 具体执行缓存委托或更新缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="Func">委托方法</param>
        /// <param name="args">至少有2个参数（从右往左（从后往前），1：是否去更新缓存，2：CacheDbTime 对象（包含时间和数据库索引）</param>
        /// <returns>List<T></returns>
        protected override async Task<ReturnList<T>> GetDataListFromCacheAsync<T>(Delegate func, object[] args)
        {
            ReturnList<T> itemList = new ReturnList<T>();
            if (args.Length < 2)
            {
                return itemList;
            }
            var cachePara = base.GetCachePara(func, args);
            string cacheKey = GetCacheKey(cachePara.Key);
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, cachePara.Expiry);
            ICacheManager<ReturnList<T>> cacheManager = cmHelper.GetReturnCacheManager<T>();
            string cacheRegion = cachePara.DbNum.ToString();
            if (cachePara.Update || await Task.Run(() => cacheManager.Exists(cacheKey, cacheRegion)) == false)//存在
            {
                itemList = await (Task<ReturnList<T>>)func.DynamicInvoke(args.Take(args.Length - 2).ToArray());
                await Task.Run(() => cacheManager.Add(cacheKey, itemList, cacheRegion));
            }
            else
            {
                itemList = await Task.Run(() => cacheManager.Get(cacheKey, cacheRegion));
            }
            return itemList;
        }
        /// <summary>
        /// 具体执行缓存委托或更新缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="func">委托方法</param>
        /// <param name="args">至少有2个参数（从右往左（从后往前），1：是否去更新缓存，2：CacheDbTime 对象（包含时间和数据库索引）</param>
        /// <returns>T></returns>
        protected override T GetDataFromCache<T>(Delegate func, object[] args)
        {
            T item = default(T);
            if (args.Length < 2)
            {
                return item;
            }
            var cachePara = base.GetCachePara(func, args);
            string cacheKey = GetCacheKey(cachePara.Key);
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, cachePara.Expiry);
            ICacheManager<T> cacheManager = cmHelper.GetCacheManager<T>();
            string cacheRegion = cachePara.DbNum.ToString();
            if (cachePara.Update || !cacheManager.Exists(cacheKey, cacheRegion))//存在
            {
                item = (T)func.DynamicInvoke(args.Take(args.Length - 2).ToArray());
                cacheManager.Add(cacheKey, item, cacheRegion);
            }
            else
            {
                item = cacheManager.Get(cacheKey);
            }
            return item;
        }
        /// <summary>
        /// 具体执行缓存委托或更新缓存
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="func">委托方法</param>
        /// <param name="args">至少有2个参数（从右往左（从后往前），1：是否去更新缓存，2：CacheDbTime 对象（包含时间和数据库索引）</param>
        /// <returns>Task<T></returns>
        protected override async Task<T> GetDataFromCacheAsync<T>(Delegate func, object[] args)
        {
            T item = default(T);
            if (args.Length < 2)
            {
                return item;
            }
            var cachePara = base.GetCachePara(func, args);
            string cacheKey = GetCacheKey(cachePara.Key);
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, cachePara.Expiry);
            ICacheManager<T> cacheManager = cmHelper.GetCacheManager<T>();
            string cacheRegion = cachePara.DbNum.ToString();
            if (cachePara.Update || await Task.Run(() => cacheManager.Exists(cacheKey, cacheRegion)) == false)//存在
            {
                item = await (Task<T>)func.DynamicInvoke(args.Take(args.Length - 2).ToArray());
                await Task.Run(() => cacheManager.Add(cacheKey, item, cacheRegion));
            }
            else
            {
                item = await Task.Run(() => cacheManager.Get(cacheKey, cacheRegion));
            }
            return item;
        }
        #endregion 

        #region 查询缓存
        /// <summary>
        /// 获得缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <returns></returns>
        public T GetCache<T>(BaseParaCache cachePara)
        {
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, GetDefaultTimeSpan());
            ICacheManager<T> cacheManager = cmHelper.GetCacheManager<T>();
            string cacheKey = GetCacheKey(cachePara.Key);
            return cacheManager.Get(cacheKey);
        }
        /// <summary>
        /// 获得缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <returns></returns>
        public async Task<T> GetCacheAsync<T>(BaseParaCache cachePara)
        {
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, GetDefaultTimeSpan());
            ICacheManager<T> cacheManager = cmHelper.GetCacheManager<T>();
            string cacheKey = GetCacheKey(cachePara.Key);
            return await Task.Run(() => cacheManager.Get(cacheKey));
        }

        /// <summary>
        /// 获得缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <returns></returns>
        public string GetCache(BaseParaCache cachePara)
        {
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, GetDefaultTimeSpan());
            ICacheManager<string> cacheManager = cmHelper.GetCacheManager<string>();
            string cacheKey = GetCacheKey(cachePara.Key);
            return cacheManager.Get(cacheKey);
        }

        /// <summary>
        /// 获得缓存
        /// </summary>
        /// <param name="cachePara"></param>
        /// <returns></returns>
        public async Task<string> GetCacheAsync(BaseParaCache cachePara)
        {
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, GetDefaultTimeSpan());
            ICacheManager<string> cacheManager = cmHelper.GetCacheManager<string>();
            string cacheKey = GetCacheKey(cachePara.Key);
            return await Task.Run(() => cacheManager.Get(cacheKey));
        }

        #endregion 

        #region 设置缓存
        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool SetCache<T>(ParaCache cachePara, T value)
        {
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, cachePara.Expiry);
            ICacheManager<T> cacheManager = cmHelper.GetCacheManager<T>();
            string cacheKey = _cacheConfig.CachePrefixName + cachePara.Key;
            return cacheManager.Add(cacheKey, value);
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cachePara"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public async Task<bool> SetCacheAsync<T>(ParaCache cachePara, T value)
        {
            CacheManagerProvider cmHelper = GetCacheProvider(cachePara.DbNum, cachePara.Expiry);
            ICacheManager<T> cacheManager = cmHelper.GetCacheManager<T>();
            string cacheKey = _cacheConfig.CachePrefixName + cachePara.Key;
            return await Task.Run(() => cacheManager.Add(cacheKey, value));
        }

        #endregion

        #region 清空缓存
        /// <summary>
        /// 删除缓存 
        /// </summary>
        /// <param name="cacheKey">缓存key值</param>
        /// <returns></returns>
        public bool DeleteCache(string cacheKey, int dbNum = 0)
        {
            CacheManagerProvider cmHelper = GetCacheProvider(dbNum, GetDefaultTimeSpan());
            var cacheManager = cmHelper.GetCacheManager<ViewModel>();
            bool isOk = true;
            if (string.IsNullOrEmpty(cacheKey))
            {
                cacheManager.Clear();
            }
            else
            {
                cacheKey = GetCacheKey(cacheKey);
                isOk = cacheManager.Remove(cacheKey);
            }
            return isOk;
        }
        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <param name="dbNum"></param>
        /// <returns></returns>
        public async Task<bool> DeleteCacheAsync(string cacheKey, int dbNum = 0)
        {
            CacheManagerProvider cmHelper = GetCacheProvider(dbNum, GetDefaultTimeSpan());
            var cacheManager = cmHelper.GetCacheManager<ViewModel>();
            bool isOk = true;
            if (string.IsNullOrEmpty(cacheKey))
            {
                await Task.Run(() => cacheManager.Clear());
            }
            else
            {
                cacheKey = GetCacheKey(cacheKey);
                isOk = await Task.Run(() => cacheManager.Remove(cacheKey));
            }
            return isOk;
        }
        private CacheManagerProvider GetCacheProvider(int dbNum, TimeSpan timeSpan)
        {
            return new CacheManagerProvider(dbNum, timeSpan, _cacheConfig.CachePrefixName, _cacheConfig.RedisConnStr);
        }
        private TimeSpan GetDefaultTimeSpan()
        {
            DateTime dtNow = DateTime.Now;
            return dtNow.AddHours(2) - dtNow;
        }
        #endregion
    }
}
